{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 查看FashionMNIST原始数据格式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:32.363026Z",
     "start_time": "2025-06-26T01:43:29.447990Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(<PIL.Image.Image image mode=L size=28x28 at 0x1B6F461D670>, 9)\n"
     ]
    },
    {
     "data": {
      "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAAcABwBAREA/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/9oACAEBAAA/APn+tbw1oNx4m8QWmkWx2yXD4LkZCADJJ+gFbviL4a63oc7COE3MW4hdn38duD976jNc9daDqllIsc9lKrMu4YGeMkdR7gj8KzcV7H8BtEvV16+1iWCeG1Wz8mOV02pIzupwCeuAp6Z98cZ90aIzLIlw0c0ZJ4KgjHoeOa+evjS9n/wnMcNxBPCYLKONFhA2FNzMpGenDcgd816V4K03wefC+m3NlpVhP+5QSXBiR5fMx825iMg5zwce3FdbOzTwgW90lu6uCm8eYrL02soIyCPQgggEdMGQ3cluiPNK0rJwrRQBNueuMkt+teNfGKxsdY8WWdxNqcNo66eieXMwVsb5DnH415Hp2rajpE5n02/urOUjBe3laMkehIPIrVm8eeLrhNknibVivoLtx/I1UPinxC3XXtUP1vJP8ay5JZJpGkldnduSzHJP41//2Q==",
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAAAAABXZoBIAAACS0lEQVR4AWKgA2BkYOD1ZGBgZAHZxcjIAKZBbBBm+quS8v3rj1N/GBiZGP8wMKNIMv91cnnCzuU65+X/vww8/76hSP5iMFVgZtpp2HXm8nUz02PHGUHGQTHjf9cugd//GE7f+cUo8ft0yDSEJCMDw/8TCgyMf34x/Ph3/vYfT0VphLH/GRgY3kt+Z2fl+cH5z8aSSWwHqmsZuJiZvn18p/CPkYnr7z9ZBiaofQwMjMwMPFI/frH++sr/j537K9sldhOE5H9mhnBJJg4Gbtlf7L//cQhvusaCkGT5xXDlBxsXl6rSD2Yunr9PoraeYAGZx8T4+x/DHwaGbV+/s/1/zczxm+H3P2a9jwxMDMz///z6+Y+BwW7ime9v//z78/XrXw6GbwxsX4NAYc3AICSlJhmk/oPpN+czVjbhX1zHeOz+fWR9qcnIYNkkKvCX+cMfrl+M36+HneEVVGC4x/v5GycPHxcj83GpP3+/MTB/Z2DgF0lwy3z24/49VeFfrLxsf+UBY0xqv8vDw87Ayv/4mSiTRACHIrexMdMvJjYGRlYLlpeP+X485mHje/eQ5/uPP+svKwj9+vD77y/Wf4xsaixP/z/mFvnw5jULOysHL9Mbza+P37O/+f3nN6fERwOWC+sTn937wcPGwcb88+//by/+/WX5wfPrw4fffxRfMjIweBWLv/7wl5mNhZnxPysrGysjA+NLBrZ/EpfCGJn+MTA4tYnxMzGz/GV8+f/pvy/MDP9/f2Paff0YJBAYGBg0RN/LPPx1Fx5HFDIAaCTYdiCc4RIAAAAASUVORK5CYII=",
      "text/plain": [
       "<PIL.Image.Image image mode=L size=28x28>"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from torchvision import datasets, transforms\n",
    "from deeplearning_func import EarlyStopping, ModelSaver,train_classification_model,plot_learning_curves\n",
    "from deeplearning_func import evaluate_classification_model as evaluate_model\n",
    "# 加载Fashion MNIST数据集，张量就是和numpy数组一样\n",
    "transform = transforms.Compose([])\n",
    "train_dataset = datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)\n",
    "test_dataset = datasets.FashionMNIST(root='./data', train=False, download=True, transform=transform)\n",
    "print(train_dataset[0])\n",
    "train_dataset[0][0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 加载数据并处理为tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:32.407799Z",
     "start_time": "2025-06-26T01:43:32.363026Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练集形状: (60000, 28, 28)\n",
      "训练集标签数量: 60000\n",
      "测试集形状: (10000, 28, 28)\n",
      "测试集标签数量: 10000\n"
     ]
    }
   ],
   "source": [
    "# 加载Fashion MNIST数据集，张量就是和numpy数组一样\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(),\n",
    "    transforms.Normalize((0.286,), (0.353,))  \n",
    "])\n",
    "train_dataset = datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)\n",
    "test_dataset = datasets.FashionMNIST(root='./data', train=False, download=True, transform=transform)\n",
    "\n",
    "# 获取图像和标签\n",
    "# 注意：由于使用了transform，图像已经被转换为张量且标准化\n",
    "# 我们需要从dataset中提取原始图像用于显示\n",
    "train_images = train_dataset.data.numpy()\n",
    "train_labels = train_dataset.targets.numpy()\n",
    "test_images = test_dataset.data.numpy()\n",
    "test_labels = test_dataset.targets.numpy()\n",
    "\n",
    "# 定义类别名称\n",
    "class_names = ['T-shirt/top', '裤子', '套头衫', '连衣裙', '外套',\n",
    "               '凉鞋', '衬衫', '运动鞋', '包', '短靴']\n",
    "\n",
    "# 查看数据集基本信息\n",
    "print(f\"训练集形状: {train_images.shape}\")\n",
    "print(f\"训练集标签数量: {len(train_labels)}\")\n",
    "print(f\"测试集形状: {test_images.shape}\")\n",
    "print(f\"测试集标签数量: {len(test_labels)}\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 把数据集划分为训练集55000和验证集5000，并给DataLoader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.144223Z",
     "start_time": "2025-06-26T01:43:33.135368Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练集大小: 55000\n",
      "验证集大小: 5000\n",
      "测试集大小: 10000\n",
      "批次大小: 64\n",
      "训练批次数: 860\n"
     ]
    }
   ],
   "source": [
    "# 从训练集中划分出验证集\n",
    "train_size = 55000\n",
    "val_size = 5000\n",
    "# 设置随机种子以确保每次得到相同的随机划分结果\n",
    "generator = torch.Generator().manual_seed(42)\n",
    "train_subset, val_subset = torch.utils.data.random_split(\n",
    "    train_dataset, \n",
    "    [train_size, val_size],\n",
    "    generator=generator #设置随机种子，确保每次得到相同的随机划分结果\n",
    ")\n",
    "\n",
    "# 创建数据加载器\n",
    "batch_size = 64\n",
    "train_loader = torch.utils.data.DataLoader(\n",
    "    train_subset,\n",
    "    batch_size=batch_size,\n",
    "    shuffle=True #打乱数据集，每次迭代时，数据集的顺序都会被打乱\n",
    ")\n",
    "\n",
    "val_loader = torch.utils.data.DataLoader(\n",
    "    val_subset,\n",
    "    batch_size=batch_size,\n",
    "    shuffle=False\n",
    ")\n",
    "\n",
    "test_loader = torch.utils.data.DataLoader(\n",
    "    test_dataset,\n",
    "    batch_size=batch_size,\n",
    "    shuffle=False\n",
    ")\n",
    "\n",
    "# 打印数据集大小信息\n",
    "print(f\"训练集大小: {len(train_subset)}\")\n",
    "print(f\"验证集大小: {len(val_subset)}\")\n",
    "print(f\"测试集大小: {len(test_dataset)}\")\n",
    "print(f\"批次大小: {batch_size}\")\n",
    "print(f\"训练批次数: {len(train_loader)}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.148120Z",
     "start_time": "2025-06-26T01:43:33.145230Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "55040"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "64*860"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 搭建模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([20, 100])\n"
     ]
    }
   ],
   "source": [
    "#理解每个接口的方法，单独写例子\n",
    "import torch.nn as nn\n",
    "m=nn.BatchNorm1d(100)\n",
    "x=torch.randn(20,100)\n",
    "print(m(x).shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.152657Z",
     "start_time": "2025-06-26T01:43:33.148120Z"
    }
   },
   "outputs": [],
   "source": [
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "class NeuralNetwork(nn.Module):\n",
    "    def __init__(self, layers_num=2):\n",
    "        super().__init__()\n",
    "        self.flatten = nn.Flatten()\n",
    "        # 多加几层\n",
    "        self.linear_selu_stack = nn.Sequential(\n",
    "            nn.Linear(28 * 28, 100),\n",
    "            nn.SELU(),\n",
    "        )\n",
    "        # 加19层\n",
    "        for i in range(1, layers_num):\n",
    "            self.linear_selu_stack.add_module(f\"Linear_{i}\", nn.Linear(100, 100))\n",
    "            self.linear_selu_stack.add_module(f\"selu\", nn.SELU())\n",
    "        # 输出层\n",
    "        self.linear_selu_stack.add_module(\"Output Layer\", nn.Linear(100, 10))\n",
    "        \n",
    "        # 初始化权重\n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层的权重 W\"\"\"\n",
    "        # print('''初始化权重''')\n",
    "        for m in self.modules():\n",
    "            # print(m)\n",
    "            # print('-'*50)\n",
    "            if isinstance(m, nn.Linear):#判断m是否为全连接层\n",
    "                # https://pytorch.org/docs/stable/nn.init.html\n",
    "                nn.init.xavier_uniform_(m.weight) # xavier 均匀分布初始化权重\n",
    "                nn.init.zeros_(m.bias) # 全零初始化偏置项\n",
    "        # print('''初始化权重完成''')\n",
    "    def forward(self, x):\n",
    "        # x.shape [batch size, 1, 28, 28]\n",
    "        x = self.flatten(x)  \n",
    "        # 展平后 x.shape [batch size, 28 * 28]\n",
    "        logits = self.linear_selu_stack(x)\n",
    "        # logits.shape [batch size, 10]\n",
    "        return logits\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.185031Z",
     "start_time": "2025-06-26T01:43:33.152657Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "批次图像形状: torch.Size([64, 1, 28, 28])\n",
      "批次标签形状: torch.Size([64])\n",
      "----------------------------------------------------------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "# 实例化模型\n",
    "model = NeuralNetwork(layers_num=19)\n",
    "\n",
    "# 从train_loader获取第一个批次的数据\n",
    "dataiter = iter(train_loader)\n",
    "images, labels = next(dataiter)\n",
    "\n",
    "# 查看批次数据的形状\n",
    "print(\"批次图像形状:\", images.shape)\n",
    "print(\"批次标签形状:\", labels.shape)\n",
    "\n",
    "\n",
    "print('-'*100)\n",
    "# 进行前向传播\n",
    "with torch.no_grad():  # 不需要计算梯度\n",
    "    outputs = model(images)\n",
    "    \n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.203053Z",
     "start_time": "2025-06-26T01:43:33.199532Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "需要求梯度的参数总量: 261310\n",
      "----------------------------------------------------------------------------------------------------\n",
      "模型总参数量: 261310\n",
      "\n",
      "各层参数量明细:\n",
      "linear_selu_stack.0.weight: 78400 参数\n",
      "linear_selu_stack.0.bias: 100 参数\n",
      "linear_selu_stack.Linear_1.weight: 10000 参数\n",
      "linear_selu_stack.Linear_1.bias: 100 参数\n",
      "linear_selu_stack.Linear_2.weight: 10000 参数\n",
      "linear_selu_stack.Linear_2.bias: 100 参数\n",
      "linear_selu_stack.Linear_3.weight: 10000 参数\n",
      "linear_selu_stack.Linear_3.bias: 100 参数\n",
      "linear_selu_stack.Linear_4.weight: 10000 参数\n",
      "linear_selu_stack.Linear_4.bias: 100 参数\n",
      "linear_selu_stack.Linear_5.weight: 10000 参数\n",
      "linear_selu_stack.Linear_5.bias: 100 参数\n",
      "linear_selu_stack.Linear_6.weight: 10000 参数\n",
      "linear_selu_stack.Linear_6.bias: 100 参数\n",
      "linear_selu_stack.Linear_7.weight: 10000 参数\n",
      "linear_selu_stack.Linear_7.bias: 100 参数\n",
      "linear_selu_stack.Linear_8.weight: 10000 参数\n",
      "linear_selu_stack.Linear_8.bias: 100 参数\n",
      "linear_selu_stack.Linear_9.weight: 10000 参数\n",
      "linear_selu_stack.Linear_9.bias: 100 参数\n",
      "linear_selu_stack.Linear_10.weight: 10000 参数\n",
      "linear_selu_stack.Linear_10.bias: 100 参数\n",
      "linear_selu_stack.Linear_11.weight: 10000 参数\n",
      "linear_selu_stack.Linear_11.bias: 100 参数\n",
      "linear_selu_stack.Linear_12.weight: 10000 参数\n",
      "linear_selu_stack.Linear_12.bias: 100 参数\n",
      "linear_selu_stack.Linear_13.weight: 10000 参数\n",
      "linear_selu_stack.Linear_13.bias: 100 参数\n",
      "linear_selu_stack.Linear_14.weight: 10000 参数\n",
      "linear_selu_stack.Linear_14.bias: 100 参数\n",
      "linear_selu_stack.Linear_15.weight: 10000 参数\n",
      "linear_selu_stack.Linear_15.bias: 100 参数\n",
      "linear_selu_stack.Linear_16.weight: 10000 参数\n",
      "linear_selu_stack.Linear_16.bias: 100 参数\n",
      "linear_selu_stack.Linear_17.weight: 10000 参数\n",
      "linear_selu_stack.Linear_17.bias: 100 参数\n",
      "linear_selu_stack.Linear_18.weight: 10000 参数\n",
      "linear_selu_stack.Linear_18.bias: 100 参数\n",
      "linear_selu_stack.Output Layer.weight: 1000 参数\n",
      "linear_selu_stack.Output Layer.bias: 10 参数\n"
     ]
    }
   ],
   "source": [
    "# 统计需要求梯度的参数总量\n",
    "trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\n",
    "print(f\"需要求梯度的参数总量: {trainable_params}\")\n",
    "\n",
    "print('-'*100)\n",
    "\n",
    "# 计算模型的总参数量\n",
    "total_params = sum(p.numel() for p in model.parameters())\n",
    "print(f\"模型总参数量: {total_params}\")\n",
    "\n",
    "# 查看每层参数量明细\n",
    "print(\"\\n各层参数量明细:\")\n",
    "for name, param in model.named_parameters():\n",
    "    print(f\"{name}: {param.numel()} 参数\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.217395Z",
     "start_time": "2025-06-26T01:43:33.203561Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('linear_selu_stack.0.weight',\n",
       "              tensor([[-0.0531, -0.0016,  0.0516,  ..., -0.0283, -0.0237, -0.0078],\n",
       "                      [ 0.0202,  0.0397, -0.0727,  ..., -0.0009, -0.0337,  0.0628],\n",
       "                      [-0.0514,  0.0595,  0.0021,  ..., -0.0229,  0.0070,  0.0387],\n",
       "                      ...,\n",
       "                      [-0.0098,  0.0541,  0.0754,  ...,  0.0343,  0.0398,  0.0147],\n",
       "                      [ 0.0773, -0.0301, -0.0277,  ...,  0.0409, -0.0424, -0.0731],\n",
       "                      [-0.0584, -0.0554,  0.0259,  ...,  0.0388,  0.0272, -0.0120]])),\n",
       "             ('linear_selu_stack.0.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_1.weight',\n",
       "              tensor([[ 0.1060,  0.1252, -0.1350,  ..., -0.0959,  0.0787,  0.0996],\n",
       "                      [-0.1243, -0.0297, -0.0035,  ..., -0.1496, -0.1447,  0.1193],\n",
       "                      [-0.0223, -0.1302,  0.0291,  ...,  0.0186, -0.1591,  0.1379],\n",
       "                      ...,\n",
       "                      [ 0.1017, -0.0173,  0.1144,  ...,  0.0969, -0.1698,  0.0861],\n",
       "                      [ 0.0712,  0.1178,  0.1472,  ..., -0.0045, -0.0600, -0.0904],\n",
       "                      [-0.0005, -0.1327,  0.1577,  ..., -0.1210, -0.1371, -0.0064]])),\n",
       "             ('linear_selu_stack.Linear_1.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_2.weight',\n",
       "              tensor([[-0.1274,  0.1215,  0.1257,  ..., -0.0175,  0.0455,  0.0442],\n",
       "                      [-0.1471,  0.0379, -0.0102,  ...,  0.1205, -0.1402, -0.1264],\n",
       "                      [-0.0383,  0.1452, -0.0614,  ...,  0.1056, -0.0476,  0.1556],\n",
       "                      ...,\n",
       "                      [ 0.1621,  0.0640,  0.0631,  ..., -0.1141,  0.0649,  0.0825],\n",
       "                      [-0.0576,  0.0786, -0.0931,  ..., -0.1616,  0.1116, -0.0273],\n",
       "                      [-0.0203, -0.1470,  0.0759,  ..., -0.1514, -0.0912,  0.1575]])),\n",
       "             ('linear_selu_stack.Linear_2.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_3.weight',\n",
       "              tensor([[ 0.0806, -0.0994,  0.0848,  ..., -0.1562, -0.0576,  0.0347],\n",
       "                      [ 0.0517,  0.1485,  0.1301,  ..., -0.0793,  0.0536, -0.0066],\n",
       "                      [-0.1471, -0.1000, -0.1256,  ...,  0.1315, -0.0528, -0.0193],\n",
       "                      ...,\n",
       "                      [ 0.0751,  0.1262,  0.0242,  ..., -0.1125,  0.0606,  0.0269],\n",
       "                      [ 0.0527, -0.1720, -0.0692,  ..., -0.0735, -0.0704, -0.0398],\n",
       "                      [ 0.0619, -0.0902, -0.1019,  ..., -0.0404,  0.1396,  0.0958]])),\n",
       "             ('linear_selu_stack.Linear_3.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_4.weight',\n",
       "              tensor([[ 1.5648e-01,  8.3541e-02,  1.3156e-01,  ..., -9.8943e-03,\n",
       "                       -7.9880e-02, -7.6509e-02],\n",
       "                      [ 4.0604e-02, -7.4960e-02, -1.4802e-01,  ...,  4.7462e-03,\n",
       "                        7.3718e-02, -5.7234e-02],\n",
       "                      [-1.1133e-01, -1.0551e-01,  4.1994e-02,  ...,  1.5932e-01,\n",
       "                       -6.6635e-02, -3.7039e-02],\n",
       "                      ...,\n",
       "                      [ 1.3199e-01, -1.5058e-01, -9.9862e-02,  ..., -1.2427e-01,\n",
       "                        2.1453e-02, -5.1097e-03],\n",
       "                      [-1.3233e-01, -5.2852e-02,  1.4026e-04,  ..., -1.4464e-01,\n",
       "                        4.7211e-03, -1.5641e-01],\n",
       "                      [-6.5762e-02,  1.1208e-01,  5.9092e-02,  ...,  1.3997e-01,\n",
       "                        1.0026e-01, -2.8984e-02]])),\n",
       "             ('linear_selu_stack.Linear_4.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_5.weight',\n",
       "              tensor([[ 1.2713e-01,  1.0564e-01, -1.0363e-01,  ...,  1.6098e-02,\n",
       "                       -1.0787e-01,  8.5910e-02],\n",
       "                      [ 1.0935e-01,  9.7582e-02,  1.2609e-01,  ..., -2.4921e-02,\n",
       "                       -3.5041e-02, -6.3650e-03],\n",
       "                      [ 5.5147e-02, -1.4598e-01, -1.1694e-01,  ..., -1.6426e-01,\n",
       "                        1.4388e-01,  1.8513e-03],\n",
       "                      ...,\n",
       "                      [ 1.2700e-01,  1.4659e-01,  1.3509e-01,  ...,  8.7331e-02,\n",
       "                        1.1746e-01,  1.5023e-01],\n",
       "                      [-1.0842e-01, -1.1034e-01, -4.4094e-02,  ...,  1.6715e-01,\n",
       "                        1.2470e-01,  6.9439e-05],\n",
       "                      [ 6.6653e-02, -6.0478e-02, -9.8112e-02,  ..., -4.3051e-02,\n",
       "                       -4.8708e-02, -1.3662e-01]])),\n",
       "             ('linear_selu_stack.Linear_5.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_6.weight',\n",
       "              tensor([[ 0.0288, -0.0883,  0.1725,  ...,  0.0484, -0.1452,  0.0945],\n",
       "                      [ 0.0992, -0.1707, -0.0585,  ...,  0.0459,  0.1136,  0.1085],\n",
       "                      [-0.0465, -0.0716,  0.0810,  ...,  0.0554, -0.0622, -0.1147],\n",
       "                      ...,\n",
       "                      [-0.1314, -0.1076, -0.0027,  ..., -0.1109, -0.0405,  0.0848],\n",
       "                      [-0.1361, -0.1259,  0.0224,  ...,  0.0005,  0.0366,  0.0927],\n",
       "                      [-0.1296,  0.0744,  0.1350,  ..., -0.1209,  0.0991, -0.0054]])),\n",
       "             ('linear_selu_stack.Linear_6.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_7.weight',\n",
       "              tensor([[ 0.0199,  0.0593, -0.1635,  ..., -0.1635,  0.1700,  0.1178],\n",
       "                      [-0.0389, -0.0210,  0.0261,  ..., -0.0456,  0.0262, -0.0701],\n",
       "                      [ 0.0913, -0.0664, -0.0858,  ...,  0.0166,  0.0007,  0.0243],\n",
       "                      ...,\n",
       "                      [-0.1244,  0.0581,  0.0602,  ..., -0.0020,  0.1408, -0.0084],\n",
       "                      [-0.0215, -0.0267, -0.0100,  ...,  0.0028,  0.1161, -0.0116],\n",
       "                      [-0.0736, -0.1282,  0.0176,  ..., -0.1330, -0.1414,  0.0521]])),\n",
       "             ('linear_selu_stack.Linear_7.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_8.weight',\n",
       "              tensor([[-0.1670,  0.1176,  0.1718,  ...,  0.1179,  0.0557,  0.1137],\n",
       "                      [-0.0331,  0.0228,  0.0568,  ..., -0.0921, -0.0590, -0.0507],\n",
       "                      [ 0.1245, -0.0161,  0.0908,  ...,  0.0527,  0.0093,  0.1131],\n",
       "                      ...,\n",
       "                      [ 0.1346, -0.0564,  0.0146,  ..., -0.1228, -0.0660, -0.1235],\n",
       "                      [-0.1392,  0.0101,  0.0559,  ...,  0.1043, -0.0619,  0.1481],\n",
       "                      [-0.0175,  0.0941, -0.0842,  ...,  0.1144,  0.1348,  0.1154]])),\n",
       "             ('linear_selu_stack.Linear_8.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_9.weight',\n",
       "              tensor([[ 0.0169, -0.0483, -0.0513,  ...,  0.0364, -0.1345,  0.1460],\n",
       "                      [ 0.0689, -0.0515,  0.1259,  ...,  0.0078,  0.0390,  0.1213],\n",
       "                      [-0.0956,  0.1396,  0.0609,  ..., -0.1706,  0.0911, -0.0994],\n",
       "                      ...,\n",
       "                      [-0.0752,  0.0436, -0.0774,  ..., -0.1185,  0.0563,  0.0695],\n",
       "                      [-0.1688,  0.1464,  0.0429,  ...,  0.0304,  0.0499,  0.0493],\n",
       "                      [ 0.0517, -0.0322, -0.0603,  ...,  0.0251, -0.0516,  0.0088]])),\n",
       "             ('linear_selu_stack.Linear_9.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_10.weight',\n",
       "              tensor([[ 0.0337,  0.0065,  0.0923,  ..., -0.1014, -0.1721,  0.1173],\n",
       "                      [-0.0019, -0.1541,  0.0263,  ..., -0.1331,  0.0304,  0.1669],\n",
       "                      [-0.0975, -0.0912,  0.0691,  ...,  0.0854,  0.0043, -0.0444],\n",
       "                      ...,\n",
       "                      [-0.1270,  0.1012,  0.0420,  ...,  0.1230, -0.0478,  0.1374],\n",
       "                      [ 0.0649,  0.0730, -0.0418,  ...,  0.1228, -0.0074,  0.0471],\n",
       "                      [-0.0318, -0.1326, -0.0585,  ...,  0.1399,  0.0164, -0.0995]])),\n",
       "             ('linear_selu_stack.Linear_10.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_11.weight',\n",
       "              tensor([[ 0.1324, -0.1342, -0.1128,  ..., -0.1084, -0.0676,  0.1593],\n",
       "                      [ 0.1140,  0.0196,  0.0510,  ..., -0.0992, -0.1172, -0.1402],\n",
       "                      [ 0.0006, -0.1261,  0.0977,  ...,  0.1121, -0.0543, -0.1575],\n",
       "                      ...,\n",
       "                      [ 0.1278, -0.1553,  0.0695,  ..., -0.0904,  0.1574,  0.0105],\n",
       "                      [-0.1276, -0.0407, -0.0287,  ...,  0.1476, -0.1420,  0.0181],\n",
       "                      [-0.0323, -0.0308, -0.0086,  ..., -0.0740,  0.1095,  0.0009]])),\n",
       "             ('linear_selu_stack.Linear_11.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_12.weight',\n",
       "              tensor([[-0.1122, -0.1437, -0.1391,  ..., -0.1179, -0.1269,  0.0185],\n",
       "                      [-0.1109, -0.1068, -0.1138,  ..., -0.0644,  0.1442,  0.0828],\n",
       "                      [-0.0492,  0.0584, -0.0208,  ..., -0.0991, -0.1249,  0.0619],\n",
       "                      ...,\n",
       "                      [-0.1728, -0.0844, -0.1528,  ..., -0.0086, -0.0009,  0.1612],\n",
       "                      [ 0.0899, -0.0202, -0.1255,  ...,  0.1209,  0.1524, -0.0681],\n",
       "                      [ 0.0375,  0.0540,  0.0014,  ...,  0.1216,  0.0159,  0.0936]])),\n",
       "             ('linear_selu_stack.Linear_12.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_13.weight',\n",
       "              tensor([[ 0.1721,  0.0295, -0.0474,  ...,  0.0749,  0.0872, -0.0125],\n",
       "                      [ 0.1375,  0.1066,  0.1262,  ...,  0.1233, -0.1059,  0.1104],\n",
       "                      [-0.1057,  0.0128,  0.0560,  ..., -0.1282, -0.1135,  0.0140],\n",
       "                      ...,\n",
       "                      [-0.1271,  0.0920, -0.0070,  ...,  0.0923, -0.1370,  0.0562],\n",
       "                      [ 0.0901, -0.0134, -0.1208,  ..., -0.0692, -0.0080,  0.1535],\n",
       "                      [ 0.0494,  0.0613,  0.0376,  ...,  0.1046,  0.1390,  0.0066]])),\n",
       "             ('linear_selu_stack.Linear_13.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_14.weight',\n",
       "              tensor([[ 0.1268, -0.0930, -0.1100,  ..., -0.1287, -0.1334, -0.1380],\n",
       "                      [ 0.1563,  0.1043,  0.1521,  ..., -0.0878,  0.0974,  0.1273],\n",
       "                      [ 0.1085, -0.1680,  0.0881,  ..., -0.0772,  0.0966, -0.1421],\n",
       "                      ...,\n",
       "                      [-0.0015,  0.0045,  0.1500,  ...,  0.1396, -0.0852,  0.0459],\n",
       "                      [-0.0794,  0.0518,  0.0088,  ...,  0.0102,  0.1364, -0.0706],\n",
       "                      [-0.0349,  0.0313,  0.0739,  ..., -0.0728,  0.1001,  0.1017]])),\n",
       "             ('linear_selu_stack.Linear_14.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_15.weight',\n",
       "              tensor([[-0.1660,  0.1388,  0.0040,  ..., -0.1620,  0.0751,  0.0052],\n",
       "                      [ 0.0863, -0.0180, -0.1611,  ..., -0.1659, -0.1207,  0.1723],\n",
       "                      [ 0.1555,  0.0477,  0.0796,  ...,  0.0281, -0.0157,  0.1082],\n",
       "                      ...,\n",
       "                      [ 0.0997, -0.1429, -0.0850,  ...,  0.0455, -0.1099, -0.0391],\n",
       "                      [-0.0356, -0.1417,  0.0143,  ..., -0.0410, -0.0286,  0.1508],\n",
       "                      [-0.0768, -0.1520, -0.1445,  ...,  0.0239,  0.0818, -0.0376]])),\n",
       "             ('linear_selu_stack.Linear_15.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_16.weight',\n",
       "              tensor([[ 0.1251,  0.1078,  0.0734,  ..., -0.0560,  0.1231,  0.0569],\n",
       "                      [-0.0702, -0.1047,  0.0488,  ...,  0.0537, -0.0352,  0.1390],\n",
       "                      [-0.1214,  0.1102,  0.1583,  ...,  0.1352,  0.1229, -0.0523],\n",
       "                      ...,\n",
       "                      [-0.0773,  0.0748,  0.1306,  ...,  0.1529,  0.1315, -0.1411],\n",
       "                      [-0.0814,  0.1582, -0.1708,  ...,  0.0121, -0.1389, -0.0357],\n",
       "                      [-0.0716, -0.0379, -0.0853,  ..., -0.1074, -0.1265, -0.1252]])),\n",
       "             ('linear_selu_stack.Linear_16.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_17.weight',\n",
       "              tensor([[-0.1705,  0.0659,  0.0086,  ..., -0.1652,  0.0320,  0.0378],\n",
       "                      [-0.1568,  0.0373,  0.0461,  ..., -0.0779,  0.1436,  0.0189],\n",
       "                      [ 0.0425,  0.0453,  0.0332,  ...,  0.1370,  0.1532, -0.0442],\n",
       "                      ...,\n",
       "                      [ 0.0549,  0.0357, -0.0404,  ...,  0.1612,  0.1063, -0.0121],\n",
       "                      [-0.0941, -0.1434,  0.1304,  ...,  0.1440, -0.0695, -0.0795],\n",
       "                      [ 0.1636,  0.1651, -0.0981,  ..., -0.1322,  0.0585,  0.1630]])),\n",
       "             ('linear_selu_stack.Linear_17.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_18.weight',\n",
       "              tensor([[ 0.0718, -0.0317, -0.1456,  ...,  0.0571, -0.1550,  0.0385],\n",
       "                      [ 0.0939, -0.1573, -0.0273,  ..., -0.1338, -0.0715,  0.0158],\n",
       "                      [ 0.0113, -0.0432,  0.0323,  ..., -0.0460,  0.0701, -0.0464],\n",
       "                      ...,\n",
       "                      [ 0.0409,  0.1584, -0.1129,  ..., -0.1097,  0.1391,  0.0550],\n",
       "                      [ 0.1523, -0.1719, -0.0639,  ...,  0.0919,  0.1011, -0.1256],\n",
       "                      [-0.0321,  0.0834,  0.1230,  ...,  0.1512,  0.1072,  0.0525]])),\n",
       "             ('linear_selu_stack.Linear_18.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Output Layer.weight',\n",
       "              tensor([[-0.0392,  0.1139,  0.1529,  0.2084,  0.0952, -0.0779,  0.1752,  0.1833,\n",
       "                        0.0972, -0.0784, -0.1614, -0.1412, -0.0727, -0.0675, -0.2191, -0.1250,\n",
       "                       -0.0269, -0.1074,  0.2202,  0.2018,  0.1357, -0.2139,  0.0314, -0.1284,\n",
       "                        0.0790, -0.0523,  0.0460,  0.0436, -0.0376, -0.0360, -0.0216,  0.0937,\n",
       "                        0.0175,  0.1159,  0.1641, -0.2214, -0.0923,  0.1108,  0.1088,  0.2323,\n",
       "                       -0.2107, -0.0800,  0.1673,  0.1086, -0.0779, -0.1994,  0.1838,  0.0236,\n",
       "                       -0.0044,  0.1801,  0.1539,  0.0065, -0.1166,  0.2231, -0.1357,  0.1949,\n",
       "                        0.2093,  0.0931,  0.1206, -0.0281,  0.1130, -0.2242, -0.0684,  0.0526,\n",
       "                        0.2092,  0.1411,  0.2239,  0.2311,  0.1532, -0.2284, -0.0725,  0.0560,\n",
       "                       -0.0529, -0.1800,  0.2170,  0.0628,  0.0888,  0.1198, -0.1202, -0.0346,\n",
       "                       -0.1433,  0.1486,  0.1047,  0.0033, -0.1446, -0.2314,  0.1912,  0.0221,\n",
       "                        0.2244, -0.0665,  0.1341, -0.2272, -0.2109,  0.1193, -0.2283, -0.1602,\n",
       "                       -0.1231,  0.2004, -0.0363, -0.1242],\n",
       "                      [ 0.1863, -0.2120,  0.0524,  0.0620,  0.1612, -0.1529,  0.0941,  0.0799,\n",
       "                        0.0718, -0.0535,  0.0395, -0.0271,  0.0017, -0.2005,  0.0555, -0.0587,\n",
       "                       -0.2260,  0.0107, -0.2231, -0.0107, -0.2122, -0.1294, -0.0800,  0.1688,\n",
       "                        0.1072, -0.0577,  0.2053, -0.0441, -0.0352, -0.2049,  0.0126,  0.0152,\n",
       "                       -0.2309, -0.0923,  0.0301, -0.0706,  0.1369, -0.0843, -0.0122,  0.1655,\n",
       "                       -0.0720, -0.1136, -0.2108, -0.2333,  0.1809,  0.0225, -0.2075,  0.0415,\n",
       "                        0.0870,  0.0926,  0.1955,  0.0983, -0.1349, -0.0013, -0.1520,  0.0681,\n",
       "                       -0.1634, -0.0052, -0.1221, -0.1917, -0.1781, -0.0985,  0.1198,  0.2292,\n",
       "                       -0.1755, -0.1598, -0.0928, -0.1357, -0.1812, -0.0468,  0.0206, -0.2201,\n",
       "                        0.0133,  0.0557,  0.1152, -0.0872, -0.2274, -0.0323,  0.2290,  0.1039,\n",
       "                       -0.2181,  0.0975,  0.1657, -0.1458, -0.0317,  0.1243,  0.1565, -0.1646,\n",
       "                        0.1543, -0.0036,  0.0162,  0.1002,  0.1526,  0.2211, -0.0085, -0.1403,\n",
       "                        0.0009, -0.0250,  0.2305,  0.0608],\n",
       "                      [ 0.0176,  0.0449, -0.1178,  0.1281,  0.0587, -0.1099, -0.1754, -0.2218,\n",
       "                       -0.1034, -0.1284,  0.1309, -0.0035,  0.0428,  0.1609,  0.0330,  0.1216,\n",
       "                        0.0366, -0.0186,  0.0638, -0.0301,  0.1184, -0.1309, -0.1849,  0.1078,\n",
       "                       -0.2039,  0.2164,  0.0885, -0.1464,  0.1382, -0.1858, -0.1083,  0.1140,\n",
       "                       -0.2259, -0.0037, -0.0005, -0.0661,  0.0803,  0.0549, -0.0112, -0.1557,\n",
       "                       -0.2118, -0.2098,  0.1310, -0.2317, -0.1186,  0.0591,  0.1771, -0.1159,\n",
       "                        0.1995,  0.1814,  0.0868, -0.1787,  0.1027,  0.2280, -0.0723, -0.1874,\n",
       "                       -0.0324,  0.1401, -0.2117,  0.1947,  0.1049,  0.0478,  0.1300, -0.1084,\n",
       "                        0.1377, -0.2063, -0.1081,  0.1569, -0.2127, -0.0230, -0.2213,  0.0670,\n",
       "                       -0.0501,  0.0536,  0.1473, -0.0705, -0.1921,  0.2198,  0.0789,  0.1994,\n",
       "                        0.1697,  0.1234, -0.1363, -0.1757,  0.2044, -0.1377, -0.0580,  0.1382,\n",
       "                        0.2174,  0.0018, -0.0266, -0.0598,  0.1837,  0.1811, -0.1106,  0.0570,\n",
       "                        0.1732,  0.0387, -0.1603,  0.1080],\n",
       "                      [-0.1205, -0.2330,  0.0832,  0.1843, -0.1926, -0.1609, -0.0847,  0.0908,\n",
       "                        0.0919, -0.1910, -0.1855, -0.0439, -0.1094, -0.1588,  0.0258,  0.1350,\n",
       "                        0.0537, -0.0998, -0.1749,  0.0238,  0.1674, -0.1109,  0.0509, -0.0542,\n",
       "                        0.0508,  0.1974,  0.0620, -0.0514,  0.2263,  0.0321,  0.1058,  0.2195,\n",
       "                       -0.1476, -0.1441, -0.1655,  0.1308,  0.0177,  0.0074, -0.0115,  0.1189,\n",
       "                       -0.0721, -0.1943,  0.0546, -0.1918,  0.0633, -0.0418, -0.1217,  0.0597,\n",
       "                        0.1447, -0.1668, -0.1204, -0.2008, -0.0948, -0.1722, -0.1486, -0.1085,\n",
       "                       -0.1841,  0.1013, -0.1980, -0.0648, -0.0962,  0.0146,  0.1666,  0.0377,\n",
       "                        0.1044,  0.0320, -0.0404, -0.0719,  0.1815, -0.2221,  0.0797,  0.1013,\n",
       "                        0.1675,  0.0262,  0.0786, -0.2075,  0.1601, -0.0434,  0.1074, -0.1345,\n",
       "                       -0.0443,  0.2211,  0.1252, -0.1631, -0.0451,  0.1210, -0.1096,  0.1932,\n",
       "                       -0.1798,  0.1282, -0.0545,  0.0546, -0.1959, -0.0979, -0.1013, -0.1995,\n",
       "                       -0.0203,  0.1989, -0.0572, -0.1923],\n",
       "                      [ 0.2135,  0.1020, -0.1383,  0.1182, -0.0069, -0.1837, -0.0856,  0.1763,\n",
       "                       -0.1183,  0.0918, -0.1540,  0.1031, -0.1244, -0.1010,  0.1079,  0.1539,\n",
       "                        0.1602,  0.1290, -0.1626, -0.2244,  0.1995, -0.1469,  0.1609, -0.0076,\n",
       "                       -0.1712,  0.0497,  0.1556, -0.0174,  0.0856,  0.0920,  0.1789,  0.1511,\n",
       "                        0.2180, -0.1706,  0.1279,  0.0167,  0.1759, -0.1481,  0.0884, -0.1649,\n",
       "                       -0.0919, -0.0039,  0.0161, -0.0649,  0.1034,  0.1187, -0.0098, -0.1473,\n",
       "                       -0.0493,  0.0369,  0.2100,  0.0364, -0.2246,  0.0751,  0.1915,  0.1905,\n",
       "                        0.1207,  0.1488, -0.1409, -0.0735,  0.1774, -0.1018,  0.0120,  0.0551,\n",
       "                        0.1160,  0.0221,  0.0704, -0.0004,  0.0198,  0.0695, -0.0921, -0.0267,\n",
       "                       -0.0166,  0.2023, -0.1587, -0.0476, -0.1470,  0.0042, -0.0354,  0.0573,\n",
       "                        0.2034, -0.0635, -0.0714, -0.1965, -0.0996,  0.1637, -0.1780, -0.0070,\n",
       "                        0.1949, -0.0798,  0.1985, -0.0851,  0.2169, -0.0901,  0.2176, -0.0391,\n",
       "                       -0.2046, -0.0816,  0.1527, -0.0790],\n",
       "                      [-0.1489,  0.0555, -0.1938, -0.1489, -0.1804, -0.2182, -0.2090,  0.1428,\n",
       "                       -0.0296, -0.1389, -0.1028,  0.1694, -0.1020, -0.0583,  0.0218,  0.1557,\n",
       "                        0.2115,  0.0376,  0.1930, -0.1780,  0.0241,  0.1549, -0.1283,  0.1662,\n",
       "                       -0.0205,  0.2253,  0.1812,  0.1122,  0.2015, -0.0451,  0.0195,  0.1310,\n",
       "                        0.1103, -0.1814, -0.1241,  0.0356, -0.2233,  0.0087, -0.0198,  0.1603,\n",
       "                       -0.1061, -0.2202,  0.1366, -0.0255,  0.0174,  0.1122,  0.0700,  0.0675,\n",
       "                       -0.2058,  0.0136,  0.2239, -0.0256,  0.0334,  0.2292,  0.0864, -0.0461,\n",
       "                        0.1034, -0.1929, -0.1783, -0.0175, -0.0961,  0.1057,  0.1194, -0.0635,\n",
       "                        0.1560, -0.1323, -0.0095, -0.1038,  0.1475, -0.0214, -0.0752, -0.1028,\n",
       "                       -0.0864,  0.0058,  0.1273,  0.1026,  0.1873,  0.0582,  0.0485,  0.0222,\n",
       "                        0.1066, -0.1340, -0.2088, -0.0826,  0.0390, -0.1892,  0.0072, -0.2171,\n",
       "                        0.1768, -0.2177,  0.1696,  0.0868, -0.1638,  0.0564, -0.2314, -0.2080,\n",
       "                        0.1032, -0.0364,  0.0175,  0.0948],\n",
       "                      [-0.0627, -0.1754, -0.0602, -0.0131,  0.1403,  0.2314, -0.1023,  0.2308,\n",
       "                       -0.1142,  0.1110, -0.1867, -0.0489, -0.1073,  0.0577,  0.1121,  0.2014,\n",
       "                       -0.1568, -0.0570, -0.0668, -0.2120,  0.2014,  0.0032, -0.1541, -0.1022,\n",
       "                       -0.0569, -0.0669,  0.1911,  0.0720,  0.1865, -0.0471, -0.0585,  0.1018,\n",
       "                        0.1210,  0.1219, -0.1330, -0.1546, -0.0236, -0.1523,  0.0318,  0.2323,\n",
       "                        0.0074,  0.0704,  0.1383,  0.2001,  0.0700,  0.1864,  0.0298, -0.0225,\n",
       "                       -0.0882, -0.1674,  0.0481,  0.2045, -0.0723, -0.0373, -0.1287, -0.1588,\n",
       "                        0.1867, -0.0881, -0.0282, -0.1359,  0.1745, -0.0213,  0.2268,  0.0179,\n",
       "                        0.1084,  0.2068,  0.0103,  0.2114, -0.1767,  0.1318,  0.0254, -0.0692,\n",
       "                        0.2084, -0.1115,  0.2035, -0.1791,  0.0481, -0.1390,  0.1078, -0.0811,\n",
       "                       -0.0970,  0.2054,  0.1574,  0.1698,  0.0470,  0.1972,  0.0344, -0.1179,\n",
       "                        0.1174, -0.1598, -0.0709, -0.0040,  0.1855,  0.0919, -0.1532,  0.1425,\n",
       "                       -0.1040,  0.0038,  0.1705,  0.1777],\n",
       "                      [ 0.1052, -0.0506, -0.2084, -0.1839,  0.1085, -0.0009,  0.1798, -0.1790,\n",
       "                        0.1974,  0.2259, -0.2070,  0.0670,  0.1105, -0.0236, -0.0098,  0.1738,\n",
       "                        0.1367,  0.0783, -0.0082,  0.0460, -0.1140,  0.0687,  0.1274, -0.2023,\n",
       "                        0.1334, -0.1201,  0.2093,  0.0621, -0.2096, -0.2271, -0.1467, -0.1669,\n",
       "                       -0.1207,  0.1174, -0.0774, -0.0780,  0.1555,  0.0073, -0.0028,  0.0686,\n",
       "                        0.1466,  0.1134, -0.1365,  0.0394,  0.1817, -0.1721, -0.0338, -0.1604,\n",
       "                        0.0435, -0.0798, -0.0905, -0.2158, -0.0108, -0.1735,  0.1406,  0.1467,\n",
       "                       -0.0020, -0.0185,  0.1181,  0.0205,  0.0339, -0.1921,  0.0487, -0.1204,\n",
       "                        0.1746, -0.0377, -0.0428,  0.1134,  0.0790, -0.2195,  0.0165, -0.1787,\n",
       "                        0.1515, -0.0940,  0.1312, -0.2040, -0.0319,  0.0669, -0.0584,  0.1674,\n",
       "                        0.2058,  0.0749,  0.1818, -0.0484, -0.2221, -0.2051, -0.0161,  0.0004,\n",
       "                        0.2173,  0.2045, -0.0117,  0.1231,  0.0464,  0.2187, -0.1524, -0.0851,\n",
       "                        0.0676,  0.1894, -0.2083, -0.0185],\n",
       "                      [ 0.1768, -0.2088, -0.0406,  0.0673, -0.1966, -0.2232,  0.2032,  0.1678,\n",
       "                       -0.0329, -0.2036, -0.1438, -0.0867, -0.2093,  0.1432, -0.2272, -0.2100,\n",
       "                       -0.1211, -0.0292, -0.0948,  0.1276,  0.1707,  0.0224,  0.1992,  0.1732,\n",
       "                       -0.0040, -0.1050, -0.2076,  0.1343,  0.0405, -0.0501,  0.2279,  0.1093,\n",
       "                        0.0278,  0.1334, -0.1131,  0.0258,  0.0157, -0.1180,  0.0010, -0.0777,\n",
       "                       -0.1797, -0.0127,  0.0010, -0.2025,  0.1980, -0.0616, -0.1788, -0.1767,\n",
       "                        0.2245,  0.1201, -0.0895,  0.0580,  0.0869, -0.1307, -0.2027, -0.0340,\n",
       "                        0.1390,  0.0461, -0.2212, -0.1959, -0.1334, -0.0518, -0.1372,  0.2081,\n",
       "                       -0.1820,  0.2120, -0.0150, -0.0551, -0.1599,  0.1273, -0.1476,  0.0352,\n",
       "                        0.0718, -0.0507,  0.0977, -0.0833,  0.1155,  0.0912,  0.1450, -0.0946,\n",
       "                       -0.0977,  0.1093,  0.1914,  0.2248, -0.1431,  0.0101, -0.1297, -0.1780,\n",
       "                        0.2142, -0.0800,  0.0363, -0.1703, -0.0959,  0.1805, -0.2291, -0.1899,\n",
       "                        0.0947,  0.1062,  0.0503, -0.0210],\n",
       "                      [ 0.2096, -0.1727,  0.1701, -0.0870,  0.2286, -0.0772,  0.0316, -0.0967,\n",
       "                       -0.0230,  0.0607, -0.1519, -0.0180, -0.0477,  0.1882, -0.2323, -0.0780,\n",
       "                       -0.1233,  0.1220, -0.0275,  0.1333, -0.1745,  0.1277,  0.1397,  0.2025,\n",
       "                        0.1459, -0.1075,  0.0892,  0.0850, -0.0787,  0.1325, -0.0604, -0.2164,\n",
       "                        0.1397, -0.0286, -0.1337,  0.1967, -0.1845, -0.0782,  0.0660,  0.2051,\n",
       "                        0.0765,  0.1594, -0.1463,  0.0835, -0.0507,  0.1150,  0.1900,  0.0262,\n",
       "                        0.0381, -0.1599,  0.0164, -0.0451, -0.0891, -0.0057,  0.0145, -0.1969,\n",
       "                        0.1690, -0.1023,  0.0734, -0.0827, -0.0428,  0.0624,  0.0160, -0.0423,\n",
       "                       -0.1186, -0.0125,  0.0563,  0.0630, -0.0723,  0.0210,  0.0560,  0.0855,\n",
       "                        0.1703, -0.0232,  0.1894, -0.0241,  0.1911, -0.0470,  0.1653, -0.0319,\n",
       "                       -0.0876, -0.2046, -0.1657,  0.1240, -0.1118, -0.0576,  0.1621, -0.0302,\n",
       "                        0.0448, -0.2298, -0.1741, -0.0525, -0.0725, -0.1471, -0.0024, -0.1790,\n",
       "                       -0.2259, -0.0248, -0.0432,  0.0098]])),\n",
       "             ('linear_selu_stack.Output Layer.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]))])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.state_dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:40.019027Z",
     "start_time": "2025-06-26T01:43:33.217395Z"
    }
   },
   "outputs": [],
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "class TensorboardLogger:\n",
    "    \"\"\"\n",
    "    Tensorboard日志记录类：记录训练过程中的损失和准确率\n",
    "    \n",
    "    参数:\n",
    "        log_dir: 日志保存目录,log_dir的父目录不要有中文\n",
    "    \"\"\"\n",
    "    def __init__(self, log_dir='tensorboard_logs'):\n",
    "\n",
    "        import os\n",
    "        \n",
    "        # 确保日志目录存在\n",
    "        if not os.path.exists(log_dir):\n",
    "            os.makedirs(log_dir)\n",
    "            \n",
    "        self.writer = SummaryWriter(log_dir) # 实例化SummaryWriter, log_dir是log存放路径，flush_secs是每隔多少秒写入磁盘\n",
    "        \n",
    "    def log_training(self, epoch, train_loss, train_acc):\n",
    "        \"\"\"\n",
    "        记录训练数据\n",
    "        \n",
    "        参数:\n",
    "            epoch: 当前训练轮数\n",
    "            train_loss: 训练损失\n",
    "            train_acc: 训练准确率\n",
    "        \"\"\"\n",
    "        self.writer.add_scalar('训练/损失', train_loss, epoch)\n",
    "        self.writer.add_scalar('训练/准确率', train_acc, epoch)\n",
    "        \n",
    "    def log_validation(self, epoch, val_loss, val_acc):\n",
    "        \"\"\"\n",
    "        记录验证数据\n",
    "        \n",
    "        参数:\n",
    "            epoch: 当前训练轮数\n",
    "            val_loss: 验证损失\n",
    "            val_acc: 验证准确率\n",
    "        \"\"\"\n",
    "        self.writer.add_scalar('验证/损失', val_loss, epoch)\n",
    "        self.writer.add_scalar('验证/准确率', val_acc, epoch)\n",
    "    \n",
    "    def log_lr(self, epoch, lr):\n",
    "        \"\"\"\n",
    "        记录学习率\n",
    "        \n",
    "        参数:\n",
    "            epoch: 当前训练轮数\n",
    "            lr: 学习率\n",
    "        \"\"\"\n",
    "        self.writer.add_scalar('学习率', lr, epoch)\n",
    "        \n",
    "    def log_model_graph(self, model, images):\n",
    "        \"\"\"\n",
    "        记录模型结构图\n",
    "        \n",
    "        参数:\n",
    "            model: 模型\n",
    "            images: 输入图像样本\n",
    "        \"\"\"\n",
    "        self.writer.add_graph(model, images)\n",
    "        \n",
    "    def close(self):\n",
    "        \"\"\"\n",
    "        关闭Tensorboard写入器\n",
    "        \"\"\"\n",
    "        self.writer.close()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 设置交叉熵损失函数，SGD优化器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:40.023837Z",
     "start_time": "2025-06-26T01:43:40.019952Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "损失函数: CrossEntropyLoss()\n",
      "优化器: SGD (\n",
      "Parameter Group 0\n",
      "    dampening: 0\n",
      "    differentiable: False\n",
      "    foreach: None\n",
      "    fused: None\n",
      "    lr: 0.01\n",
      "    maximize: False\n",
      "    momentum: 0.9\n",
      "    nesterov: False\n",
      "    weight_decay: 0\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "model = NeuralNetwork()\n",
    "# 定义损失函数和优化器\n",
    "loss_fn = nn.CrossEntropyLoss()  # 交叉熵损失函数，适用于多分类问题，里边会做softmax，还有会把0-9标签转换成one-hot编码\n",
    "# 用少量样本就能更新权重，训练更快，且更容易跳出局部最优\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)  # SGD优化器，学习率为0.01，动量为0.9\n",
    "\n",
    "print(\"损失函数:\", loss_fn)\n",
    "print(\"优化器:\", optimizer)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:40.035848Z",
     "start_time": "2025-06-26T01:43:40.032419Z"
    }
   },
   "outputs": [],
   "source": [
    "model = NeuralNetwork(layers_num=19)\n",
    "\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)  # SGD优化器，学习率为0.01，动量为0.9"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.732814Z",
     "start_time": "2025-06-26T01:43:40.035848Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "使用设备: cuda:0\n",
      "训练开始，共43000步\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "d4e23f7a6f694e4db1e7bf0e6193274c",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/43000 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "早停触发! 最佳验证准确率: 87.4200\n",
      "早停: 在10000 步\n"
     ]
    }
   ],
   "source": [
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "print(f\"使用设备: {device}\")\n",
    "model = model.to(device) #将模型移动到GPU\n",
    "early_stopping=EarlyStopping(patience=5, delta=0.001)\n",
    "model_saver=ModelSaver(save_dir='model_weights', save_best_only=True)\n",
    "#tensorboard_logger=TensorboardLogger(log_dir='logs')\n",
    "\n",
    "model, history = train_classification_model(model, train_loader, val_loader, loss_fn, optimizer, device, num_epochs=50, early_stopping=early_stopping, model_saver=model_saver, tensorboard_logger=None)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.737721Z",
     "start_time": "2025-06-26T01:45:37.732814Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'loss': 0.39367416501045227, 'acc': 84.375, 'step': 9901},\n",
       " {'loss': 0.18359020352363586, 'acc': 92.1875, 'step': 9902},\n",
       " {'loss': 0.23432683944702148, 'acc': 93.75, 'step': 9903},\n",
       " {'loss': 0.17544293403625488, 'acc': 90.625, 'step': 9904},\n",
       " {'loss': 0.3467099964618683, 'acc': 87.5, 'step': 9905},\n",
       " {'loss': 0.31575947999954224, 'acc': 89.0625, 'step': 9906},\n",
       " {'loss': 0.4142189621925354, 'acc': 82.8125, 'step': 9907},\n",
       " {'loss': 0.3758467137813568, 'acc': 87.5, 'step': 9908},\n",
       " {'loss': 0.1792909801006317, 'acc': 92.1875, 'step': 9909},\n",
       " {'loss': 0.35155683755874634, 'acc': 87.5, 'step': 9910},\n",
       " {'loss': 0.24291151762008667, 'acc': 90.625, 'step': 9911},\n",
       " {'loss': 0.20996107161045074, 'acc': 92.1875, 'step': 9912},\n",
       " {'loss': 0.2511862814426422, 'acc': 87.5, 'step': 9913},\n",
       " {'loss': 0.34264591336250305, 'acc': 85.9375, 'step': 9914},\n",
       " {'loss': 0.3083350658416748, 'acc': 87.5, 'step': 9915},\n",
       " {'loss': 0.3027987778186798, 'acc': 89.0625, 'step': 9916},\n",
       " {'loss': 0.277239054441452, 'acc': 89.0625, 'step': 9917},\n",
       " {'loss': 0.42876023054122925, 'acc': 85.9375, 'step': 9918},\n",
       " {'loss': 0.2474372237920761, 'acc': 90.625, 'step': 9919},\n",
       " {'loss': 0.5248849987983704, 'acc': 85.9375, 'step': 9920},\n",
       " {'loss': 0.17077963054180145, 'acc': 92.1875, 'step': 9921},\n",
       " {'loss': 0.30052611231803894, 'acc': 87.5, 'step': 9922},\n",
       " {'loss': 0.11673111468553543, 'acc': 95.3125, 'step': 9923},\n",
       " {'loss': 0.2950153052806854, 'acc': 89.0625, 'step': 9924},\n",
       " {'loss': 0.2335691899061203, 'acc': 90.625, 'step': 9925},\n",
       " {'loss': 0.28567299246788025, 'acc': 92.1875, 'step': 9926},\n",
       " {'loss': 0.30820396542549133, 'acc': 87.5, 'step': 9927},\n",
       " {'loss': 0.48695823550224304, 'acc': 84.375, 'step': 9928},\n",
       " {'loss': 0.2650192081928253, 'acc': 92.1875, 'step': 9929},\n",
       " {'loss': 0.10529343038797379, 'acc': 95.3125, 'step': 9930},\n",
       " {'loss': 0.28280073404312134, 'acc': 87.5, 'step': 9931},\n",
       " {'loss': 0.15677684545516968, 'acc': 95.3125, 'step': 9932},\n",
       " {'loss': 0.5500568151473999, 'acc': 84.375, 'step': 9933},\n",
       " {'loss': 0.3210279047489166, 'acc': 85.9375, 'step': 9934},\n",
       " {'loss': 0.2997935116291046, 'acc': 85.9375, 'step': 9935},\n",
       " {'loss': 0.3297445774078369, 'acc': 85.9375, 'step': 9936},\n",
       " {'loss': 0.2154116928577423, 'acc': 92.1875, 'step': 9937},\n",
       " {'loss': 0.3519057035446167, 'acc': 82.8125, 'step': 9938},\n",
       " {'loss': 0.06986203044652939, 'acc': 100.0, 'step': 9939},\n",
       " {'loss': 0.34114882349967957, 'acc': 85.9375, 'step': 9940},\n",
       " {'loss': 0.364504873752594, 'acc': 82.8125, 'step': 9941},\n",
       " {'loss': 0.27604490518569946, 'acc': 85.9375, 'step': 9942},\n",
       " {'loss': 0.21223224699497223, 'acc': 95.3125, 'step': 9943},\n",
       " {'loss': 0.3086371421813965, 'acc': 92.1875, 'step': 9944},\n",
       " {'loss': 0.2831959128379822, 'acc': 87.5, 'step': 9945},\n",
       " {'loss': 0.2704467475414276, 'acc': 90.625, 'step': 9946},\n",
       " {'loss': 0.27085575461387634, 'acc': 90.625, 'step': 9947},\n",
       " {'loss': 0.2319183349609375, 'acc': 89.0625, 'step': 9948},\n",
       " {'loss': 0.23381465673446655, 'acc': 92.1875, 'step': 9949},\n",
       " {'loss': 0.28178897500038147, 'acc': 92.1875, 'step': 9950},\n",
       " {'loss': 0.23208244144916534, 'acc': 95.3125, 'step': 9951},\n",
       " {'loss': 0.32331299781799316, 'acc': 90.625, 'step': 9952},\n",
       " {'loss': 0.26512235403060913, 'acc': 92.1875, 'step': 9953},\n",
       " {'loss': 0.2139211744070053, 'acc': 89.0625, 'step': 9954},\n",
       " {'loss': 0.21241241693496704, 'acc': 95.3125, 'step': 9955},\n",
       " {'loss': 0.42174628376960754, 'acc': 85.9375, 'step': 9956},\n",
       " {'loss': 0.21339605748653412, 'acc': 93.75, 'step': 9957},\n",
       " {'loss': 0.5074502229690552, 'acc': 82.8125, 'step': 9958},\n",
       " {'loss': 0.3151502013206482, 'acc': 84.375, 'step': 9959},\n",
       " {'loss': 0.2847254276275635, 'acc': 89.0625, 'step': 9960},\n",
       " {'loss': 0.2161402702331543, 'acc': 89.0625, 'step': 9961},\n",
       " {'loss': 0.26641035079956055, 'acc': 93.75, 'step': 9962},\n",
       " {'loss': 0.1490207314491272, 'acc': 93.75, 'step': 9963},\n",
       " {'loss': 0.19338563084602356, 'acc': 93.75, 'step': 9964},\n",
       " {'loss': 0.12287025898694992, 'acc': 96.875, 'step': 9965},\n",
       " {'loss': 0.34615474939346313, 'acc': 85.9375, 'step': 9966},\n",
       " {'loss': 0.3012670874595642, 'acc': 90.625, 'step': 9967},\n",
       " {'loss': 0.23017145693302155, 'acc': 93.75, 'step': 9968},\n",
       " {'loss': 0.3585953712463379, 'acc': 85.9375, 'step': 9969},\n",
       " {'loss': 0.22812505066394806, 'acc': 90.625, 'step': 9970},\n",
       " {'loss': 0.2003292292356491, 'acc': 92.1875, 'step': 9971},\n",
       " {'loss': 0.3155234456062317, 'acc': 84.375, 'step': 9972},\n",
       " {'loss': 0.413884699344635, 'acc': 82.8125, 'step': 9973},\n",
       " {'loss': 0.23740845918655396, 'acc': 90.625, 'step': 9974},\n",
       " {'loss': 0.3977440595626831, 'acc': 85.9375, 'step': 9975},\n",
       " {'loss': 0.26079797744750977, 'acc': 89.0625, 'step': 9976},\n",
       " {'loss': 0.16875235736370087, 'acc': 95.3125, 'step': 9977},\n",
       " {'loss': 0.16636675596237183, 'acc': 95.3125, 'step': 9978},\n",
       " {'loss': 0.2586815655231476, 'acc': 87.5, 'step': 9979},\n",
       " {'loss': 0.37991800904273987, 'acc': 82.8125, 'step': 9980},\n",
       " {'loss': 0.27822345495224, 'acc': 90.625, 'step': 9981},\n",
       " {'loss': 0.3105771243572235, 'acc': 84.375, 'step': 9982},\n",
       " {'loss': 0.18279001116752625, 'acc': 92.1875, 'step': 9983},\n",
       " {'loss': 0.2886922061443329, 'acc': 89.0625, 'step': 9984},\n",
       " {'loss': 0.24084803462028503, 'acc': 92.1875, 'step': 9985},\n",
       " {'loss': 0.26906508207321167, 'acc': 87.5, 'step': 9986},\n",
       " {'loss': 0.17754508554935455, 'acc': 89.0625, 'step': 9987},\n",
       " {'loss': 0.34488627314567566, 'acc': 89.0625, 'step': 9988},\n",
       " {'loss': 0.22750237584114075, 'acc': 92.1875, 'step': 9989},\n",
       " {'loss': 0.3446931540966034, 'acc': 90.625, 'step': 9990},\n",
       " {'loss': 0.19221793115139008, 'acc': 93.75, 'step': 9991},\n",
       " {'loss': 0.35650959610939026, 'acc': 84.375, 'step': 9992},\n",
       " {'loss': 0.40596804022789, 'acc': 84.375, 'step': 9993},\n",
       " {'loss': 0.22673708200454712, 'acc': 90.625, 'step': 9994},\n",
       " {'loss': 0.21835491061210632, 'acc': 92.1875, 'step': 9995},\n",
       " {'loss': 0.2559870183467865, 'acc': 90.625, 'step': 9996},\n",
       " {'loss': 0.41973361372947693, 'acc': 85.9375, 'step': 9997},\n",
       " {'loss': 0.34482628107070923, 'acc': 89.0625, 'step': 9998},\n",
       " {'loss': 0.1434100866317749, 'acc': 96.875, 'step': 9999}]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "history['train'][-100:-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.741226Z",
     "start_time": "2025-06-26T01:45:37.737721Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'loss': 2.615598530960083, 'acc': 13.88, 'step': 0},\n",
       " {'loss': 0.5274061810016633, 'acc': 81.74, 'step': 500},\n",
       " {'loss': 0.47754225285053253, 'acc': 82.92, 'step': 1000},\n",
       " {'loss': 0.4394821517944336, 'acc': 84.34, 'step': 1500},\n",
       " {'loss': 0.4462450321674347, 'acc': 83.76, 'step': 2000},\n",
       " {'loss': 0.4325968278646469, 'acc': 85.44, 'step': 2500},\n",
       " {'loss': 0.42206192109584806, 'acc': 84.94, 'step': 3000},\n",
       " {'loss': 0.39718271353244783, 'acc': 86.16, 'step': 3500},\n",
       " {'loss': 0.40853331017494204, 'acc': 85.82, 'step': 4000},\n",
       " {'loss': 0.39943434245586396, 'acc': 86.12, 'step': 4500},\n",
       " {'loss': 0.39851896483898164, 'acc': 86.24, 'step': 5000},\n",
       " {'loss': 0.37001421258449557, 'acc': 86.62, 'step': 5500},\n",
       " {'loss': 0.396795761013031, 'acc': 85.9, 'step': 6000},\n",
       " {'loss': 0.3918697817802429, 'acc': 86.02, 'step': 6500},\n",
       " {'loss': 0.3803961302995682, 'acc': 86.74, 'step': 7000},\n",
       " {'loss': 0.35597910668849947, 'acc': 87.42, 'step': 7500},\n",
       " {'loss': 0.36938821892738344, 'acc': 87.38, 'step': 8000},\n",
       " {'loss': 0.36979698868989946, 'acc': 87.04, 'step': 8500},\n",
       " {'loss': 0.37204169511795043, 'acc': 87.02, 'step': 9000},\n",
       " {'loss': 0.3456856389641762, 'acc': 87.18, 'step': 9500}]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "history['val'][-1000:-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 绘制损失曲线和准确率曲线"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.744941Z",
     "start_time": "2025-06-26T01:45:37.741226Z"
    }
   },
   "outputs": [],
   "source": [
    "# 导入绘图库\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib import font_manager\n",
    "def plot_learning_curves1(history):\n",
    "    # 设置中文字体支持\n",
    "    plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体\n",
    "    plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题\n",
    "\n",
    "    # 创建一个图形，包含两个子图（损失和准确率）\n",
    "    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5))\n",
    "\n",
    "    # 绘制损失曲线\n",
    "    epochs = range(1, len(history['train_loss']) + 1)\n",
    "    ax1.plot(epochs, history['train_loss'], 'b-', label='训练损失')\n",
    "    ax1.plot(epochs, history['val_loss'], 'r-', label='验证损失')\n",
    "    ax1.set_title('训练与验证损失')\n",
    "    ax1.set_xlabel('轮次')\n",
    "    ax1.set_ylabel('损失')\n",
    "    ax1.legend()\n",
    "    ax1.grid(True)\n",
    "\n",
    "    # 绘制准确率曲线\n",
    "    ax2.plot(epochs, history['train_acc'], 'b-', label='训练准确率')\n",
    "    ax2.plot(epochs, history['val_acc'], 'r-', label='验证准确率')\n",
    "    ax2.set_title('训练与验证准确率')\n",
    "    ax2.set_xlabel('轮次')\n",
    "    ax2.set_ylabel('准确率 (%)')\n",
    "    ax2.legend()\n",
    "    ax2.grid(True)\n",
    "\n",
    "    plt.tight_layout()\n",
    "    plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.816716Z",
     "start_time": "2025-06-26T01:45:37.744941Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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bLC15Gyk5n7atGlo2rSpKg0YP348rrnmGuzevRv+/v7qOfzuEbkeHpvIlnhsIlfnNIFOWT377LMwGAxYv359qelbIksMGDCg4LZcCZODS926dfHbb7/hgQceUI/zu0dEJeH+gSoDj03k6pymdE3+43Rzc8OZM2eKPC73pSbVrG/fvjh16hQWLlxog60kVxEUFIQmTZrg0KFDBY/xu0fkenhsInvCYxO5GqcJdDw9PdG+fXssXbq04DGj0ajud+3ateCxIUOGYMaMGXjwwQcxc+ZMG20tObvU1FQcPnxYDeo043ePyPXw2ET2hMcmcjVOVbom7TvvvfdedOjQAZ06dcInn3yCtLQ01emmsOHDh+PHH3/E3XffrbqR3HzzzTbbZnIOzz//PAYPHqxKAuLi4lTnGrmKe8cddxR5Hr97RK6HxyayFR6byNU5VaBz22234ezZsxg3bhzi4+PRpk0bLFiw4IpBoEL+I5aravIftXTAGTFihE22mZzDyZMn1YHj/PnzqF69Onr06KHqneX25fjdI3ItPDaRrfDYRK5OZ5KegkRERERERE7EacboEBERERERmTHQISIiIiIip8NAh4iIiIiInA4DHSIiIiIicjoMdIiIiIiIyOkw0CEiIiIiIqfDQIeIiIiIiJwOAx0iIiIiInI6DHSIrGTUqFEYNmyYrTeDiIhI4XGJXB0DHSIiIiIicjoMdIgs9Pvvv6Nly5bw9vZGaGgo+vTpgxdeeAE//PAD/vzzT+h0OrUsX75cPf/EiRO49dZbERQUhJCQEAwdOhTHjh274orb+PHjUb16dQQEBODRRx9Fdna2DX9LIiJyFDwuERXPvYTHiagYp0+fxh133IH33nsPw4cPR0pKClatWoV77rkHsbGxSE5OxtSpU9Vz5eCRk5OD/v37o2vXrup57u7uePPNN3HDDTdg586d8PT0VM9dunQpvLy81EFIDjb33XefOli99dZbNv6NiYjInvG4RFQyBjpEFh5QcnNzMWLECNStW1c9JlfRhFxJy8rKQkRERMHzf/rpJxiNRnz77bfqapqQA45cRZODR79+/dRjcmD5/vvv4ePjg6ioKLzxxhvqatyECROg1zPxSkRExeNxiahk/KYSWaB169a4/vrr1UHklltuwTfffIOLFy+W+PwdO3bg0KFD8Pf3h5+fn1rkilpmZiYOHz5c5H3lYGImV9pSU1NVeQEREVFJeFwiKhkzOkQWcHNzw+LFi7F27VosWrQIn3/+Of73v/9hw4YNxT5fDgrt27fHzz//fMXPpO6ZiIioInhcIioZAx0iC0mqv3v37moZN26cKhWYM2eOSvPn5eUVeW67du3w66+/IiwsTA3mLO0KW0ZGhiozEOvXr1dX2SIjIyv99yEiIsfG4xJR8Vi6RmQBuUL29ttvY/PmzWqQ5+zZs3H27Fk0b94c9erVUwM5Y2JicO7cOTXgc+TIkahWrZrqaCODPo8ePapqoJ966imcPHmy4H2lk80DDzyAvXv3Yv78+XjttdfwxBNPsA6aiIhKxeMSUcmY0SGygFz9WrlyJT755BPVyUaumn344YcYMGAAOnTooA4WspbSgP/++w+9evVSz3/xxRfVQFHphlOrVi1VT134Sprcb9y4MXr27KkGjkoHnddff92mvysREdk/HpeISqYzmUymUn5ORJVM5itITEzE3Llzbb0pREREPC6R02D+kYiIiIiInA4DHSIiIiIicjosXSMiIiIiIqfDjA4RERERETkdBjpEREREROR0GOgQEREREZHTYaBDREREREROh4EOERERERE5HQY6RERERETkdBjoEBERERGR02GgQ0REREREToeBDhERERERwdn8PzDMq0wJGLanAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_learning_curves(history, sample_step=500)  #横坐标是 steps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.818553Z",
     "start_time": "2025-06-26T01:45:37.816716Z"
    }
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:48:40.300725Z",
     "start_time": "2025-06-26T01:48:39.548524Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(86.26, 0.395998552107811)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在测试集上评估模型\n",
    "test_accuracy = evaluate_model(model, test_loader, device, loss_fn)\n",
    "test_accuracy\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
